package sessionadmin

import (
	"runtime/debug"
	"sort"
	"src/config"
	"src/iinf"
	"src/log"
	"sync"
)

//Admin 会话管理
type Admin struct {
	id   int
	mu   sync.Mutex
	smap map[int]iinf.Session
}

func (a *Admin) lock() {
	if config.LockStackDump {
		log.Println(string(debug.Stack()))
		log.Println("befor admin lock")
	}
	a.mu.Lock()
	if config.LockStackDump {
		log.Println("after admin lock")
	}
}

func (a *Admin) unLock() {
	if config.LockStackDump {
		log.Println(string(debug.Stack()))
		log.Println("admin unlock")
	}
	a.mu.Unlock()
}

//AddSession AddSession
func (a *Admin) AddSession(s iinf.Session) {
	a.lock()
	defer a.unLock()

	a.smap[s.GetID()] = s
}

//DelSession DelSession
func (a *Admin) DelSession(s iinf.Session) {
	a.lock()
	defer a.unLock()

	delete(a.smap, s.GetID())
}

//GetID GetID
func (a *Admin) GetID() int {
	a.lock()
	defer a.unLock()
	//最多支持500个
	maxNum := config.MaxTransPortNum
	ia := make([]byte, maxNum)

	for _, v := range a.smap {
		ia[v.GetID()] = 1
	}

	for i := 0; i < maxNum; i++ {
		if ia[i] != 1 {
			return i
		}
	}

	return -1
}

//Show Show
func (a *Admin) Show() {
	a.lock()
	defer a.unLock()

	//排个序吧
	var keys []int
	for _, v := range a.smap {
		keys = append(keys, v.GetID())
	}
	sort.Ints(keys)
	for _, k := range keys {
		v := a.smap[k]
		if v.IsQuit() {
			continue
		}
		v.Show()
	}
}

//GetInfo GetInfo
func (a *Admin) GetInfo() string {
	a.lock()
	defer a.unLock()

	str := ""
	//排个序吧
	var keys []int
	for _, v := range a.smap {
		keys = append(keys, v.GetID())
	}
	sort.Ints(keys)
	for _, k := range keys {
		v := a.smap[k]
		str += v.GetInfo()
	}

	return str
}

// Close Close
func (a *Admin) Close() {
	a.lock()
	defer a.unLock()

	for _, v := range a.smap {
		v.Close()
	}

	a.smap = nil
}

func (a *Admin) getQuitSession() iinf.Session {
	a.lock()
	defer a.unLock()

	for _, v := range a.smap {
		if v.IsQuit() {
			return v
		}
	}

	return nil
}

// SyncSession SyncSession
func (a *Admin) SyncSession() {
	//删除废弃会话
	for {
		v := a.getQuitSession()
		if v == nil {
			break
		}
		v.Close()
		a.DelSession(v)
	}

	a.lock()
	defer a.unLock()
	for _, v := range a.smap {
		v.SyncSession()
	}
}

// GetNewAdmin GetNewAdmin
func GetNewAdmin() *Admin {
	return &Admin{
		smap: make(map[int]iinf.Session),
	}
}
